#include <cassert>
#include <cstring>
#include <iostream>
#include <cstdlib>   
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <termio.h>
#include <fcntl.h>
#include <getopt.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include "udp.h"
#include "stun.h"
#include "libt2usvr.h"
#include "libt2u.h"

#define INTERNETIO01 "gpio0"
#define CONNECTIO "gpio1"
#define INTERNET  1
#define CONNECT 2
#define MAX_LEN 200
int lport=0;
int oport=0;
bool isnat=false;
int routea=0;
char oip[200];

char uuid[MAX_LEN];
char pass[MAX_LEN];
char mtu[MAX_LEN];
char lanip[MAX_LEN];
char serverip[MAX_LEN];
char remotelanip[MAX_LEN];
char staticvpnip[MAX_LEN];
char remotevpnip[MAX_LEN];
char vpnproto[MAX_LEN];
int timeflag=0;
using namespace std;

typedef struct  send_st
{
	int oport;
	bool isnat;
	char oip[MAX_LEN];
	char pass[MAX_LEN];
	char start[MAX_LEN];
}Sendtoclient;


typedef struct  remote_st
{
	char pass[MAX_LEN];
	char reboot[MAX_LEN];
}SendRemote;


void readuci(char cmd[], char para[]) //从uci命令中获取参数
{
	FILE *fp;
	int i = 0;
	if((fp = popen(cmd,"r")) == NULL)
	{
		printf("Get serviceid false!,cmd=%s,para=%s\n",cmd,para);
		sprintf(para,"%s","00000000");
		return;
	}
	memset(para,0,sizeof(para));
	if(fgets(para,MAX_LEN, fp)!=NULL)
	{
		while(para[i] != '\n')
		{
			i++;
		}
		para[i] = '\0';
	}
	pclose(fp);
}


int *n2n()
{
	char config[200];
	char vpnmac[40];
	char uuid2[MAX_LEN];
	readuci("uci get routedif.@routedif[0].remoteid",uuid);
	readuci("uci get routedif.@routedif[0].remotepass",pass);	
	readuci("uci get routedif.@routedif[0].mtu",mtu);
	sprintf(uuid2,"%s%s",uuid,"static");
	
	if(routea==1)
		sprintf(vpnmac,"%s%c%c:%c%c:%c%c","00:11:33:",uuid[9],uuid[10],uuid[11],uuid[12],uuid[13],uuid[14]);
	else
		sprintf(vpnmac,"%s%c%c:%c%c:%c%c","00:11:22:",uuid[9],uuid[10],uuid[11],uuid[12],uuid[13],uuid[14]);
	
	int pid = fork();
	if(pid<0)
	{	
		printf("vpn2 running error!\n");
		return 0;
	}
	else if(pid == 0)
	{	
		if ((pid = fork()) < 0)      
        	{       
			printf("vpn2 running error!\n");  
			return 0;    
      		 }     
		 else if(pid>0)
		{
			exit(0);
		}
		sprintf(config,"edge  -d staticvpn  -m %s -M %s -a %s -c %s -k %s -l %s:7100",vpnmac,mtu,staticvpnip,uuid2,pass,serverip); 		
		execl("/bin/sh", "sh", "-c", config, NULL);	
	}
	else
	{
		if (waitpid(pid, NULL, 0) != pid) // wait for first child      
    		{      
         		printf("kill child one!\n");  
			return 0;       
     		} 
	}
}

void *directvpn(int lport,char ip[],int oport)
{
	system("killall openvpn");
	system("killall relayvpn");
	char config[200];
	int pid = fork();

	if(pid<0)
	{	
		printf("vpn1 running error!\n");
		return NULL;
	}
	else if(pid == 0)
	{	
		if ((pid = fork()) < 0)      
        	{       
			printf("vpn1 running error!\n");  
			return NULL;    
      		 }     
		 else if(pid>0)
		{
			exit(0);;
		}
			sprintf(config,"/jffs/sbin/openvpn --proto udp --lport %d --remote %s %d --dev tap --float --keepalive 20 180 --persist-key --persist-tun",lport,ip,oport);
			execl("/bin/sh", "sh", "-c", config, NULL);
	}

	else
	{
		if (waitpid(pid, NULL, 0) != pid) /* wait for first child */     
    		{      
				return NULL;       
     		} 
		sleep(4);
		system("/usr/sbin/brctl addif br-lan tap0");
		system("/sbin/ifconfig tap0 0.0.0.0 promisc up");
		system("/usr/sbin/iptables -A INPUT -i tap0 -j ACCEPT");
		system("/usr/sbin/iptables -A INPUT -i br-lan -j ACCEPT");
		system("/usr/sbin/iptables -A FORWARD -i br-lan -j ACCEPT");	
	}
 return NULL;
}


void *relayvpn()
{
	char config[200];
	char vpnmac[40];
	system("killall openvpn");
	system("killall relayvpn");
	readuci("uci get routedif.@routedif[0].remoteid",uuid);
	readuci("uci get routedif.@routedif[0].remotepass",pass);	
	readuci("uci get routedif.@routedif[0].mtu",mtu);
	
	if(routea==1)
		sprintf(vpnmac,"%s%c%c:%c%c:%c%c","00:11:77:",uuid[9],uuid[10],uuid[11],uuid[12],uuid[13],uuid[14]);
	else
		sprintf(vpnmac,"%s%c%c:%c%c:%c%c","00:11:88:",uuid[9],uuid[10],uuid[11],uuid[12],uuid[13],uuid[14]);
		
	int pid = fork();
	if(pid<0)
	{	
		return NULL;
	}
	else if(pid == 0)
	{	
		if ((pid = fork()) < 0)      
      	  	{       
			printf("vpn2 running error second child!\n");  
			return NULL;    
      		 }     
		 else if(pid>0)
		{
			exit(0);;
		}
		sprintf(config,"/jffs/sbin/relayvpn -r -m %s -M %s -a 0.0.0.0 -c %s -k %s -l %s:7200",vpnmac,mtu,uuid,pass,serverip);
		execl("/bin/sh", "sh", "-c", config, NULL);
	}
	else
	{
		if (waitpid(pid, NULL, 0) != pid) /* wait for first child */     
		{      
			return NULL;       
 		} 
		sleep(4);
		system("/usr/sbin/brctl addif br-lan edge0");
		system("/sbin/ifconfig edge0 0.0.0.0 promisc up");
		system("/usr/sbin/iptables -A INPUT -i edge0 -j ACCEPT");
		system("/usr/sbin/iptables -A INPUT -i br-lan -j ACCEPT");
		system("/usr/sbin/iptables -A FORWARD -i br-lan -j ACCEPT");
	}
}

void *recvthread(void *arg)
{
	Sendtoclient sendbuf,recvbuf;
	int m_socket; 
	socklen_t  len;
	struct sockaddr_in srvaddr;
	if ((m_socket = socket(AF_INET,SOCK_DGRAM,0)) < 0)		
	{
		printf("recvthread error!\n");	
		return NULL;
	}
	bzero(&srvaddr,sizeof(srvaddr));
	srvaddr.sin_family = AF_INET;
	srvaddr.sin_port = htons(7002);
	srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(m_socket, (struct sockaddr*)&srvaddr, sizeof(srvaddr))<0)
	{
		printf("recvthread bind cliaddr false!22\n");
		return NULL;
        }
	len = sizeof(srvaddr);
	while(1)
	{
		sleep(1);
		recvbuf.isnat=false;
		strcpy(recvbuf.oip,"0.0.0.0");
		strcpy(recvbuf.start,"vpn0");
		strcpy(recvbuf.pass,"");
		recvbuf.oport=0;
		
		recvfrom(m_socket, (char *)&recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&srvaddr, &len);
		struct timeval timeout={8,0};
		setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
			
		if(strcmp(recvbuf.start,"start")==0 )
			{
				testnat(&lport,&oport,oip,&isnat);
				sleep(2);
				sendbuf.isnat=isnat;
				strcpy(sendbuf.oip,oip);
				strcpy(sendbuf.pass,"");
				sendbuf.oport=oport;
				recvbuf.oport=ntohl(recvbuf.oport);

				cout<<"publicport="<<recvbuf.oport<<endl;

				
				if(isnat==true&&recvbuf.isnat==true)
					{
						strcpy(sendbuf.start,"vpn1");
						cout<<"start vpn1 thread1.....\n"<<endl;
						sendto(m_socket,(char *)&sendbuf,sizeof(sendbuf)+1, 0,(struct sockaddr*)&srvaddr,sizeof(srvaddr));
							sleep(3);
					directvpn(lport,recvbuf.oip,recvbuf.oport);
					}
				else
					{
						strcpy(sendbuf.start,"vpn2");
						cout<<"start vpn2 thread2.....\n"<<endl;
						sendto(m_socket,(char *)&sendbuf,sizeof(sendbuf)+1, 0,(struct sockaddr*)&srvaddr,sizeof(srvaddr));
						sleep(3);
						relayvpn();
					}
			}
		else
			{
				sendto(m_socket,"error",6, 0,(struct sockaddr*)&srvaddr,sizeof(srvaddr));
			}
	}
	return NULL;
}

int sendthread(char ip[])
{
	timeflag++;
	int m_socket;
	socklen_t  len;
	Sendtoclient sendbuf,recvbuf;
	struct sockaddr_in srvaddr;
	if ((m_socket = socket(AF_INET,SOCK_DGRAM,0)) < 0)		
	{
		printf("testalive socket error!\n");
		return 0;
	}
	bzero(&srvaddr,sizeof(srvaddr));
	srvaddr.sin_family = AF_INET;
	srvaddr.sin_port = htons(7002);
	srvaddr.sin_addr.s_addr = inet_addr(ip);
	struct timeval timeout={8,0};
	setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));

	testnat(&lport,&oport,oip,&isnat);
	if(timeflag>3)
		sendbuf.isnat=false;
 	else
		sendbuf.isnat=isnat;

	strcpy(sendbuf.oip,oip);
	strcpy(sendbuf.start,"start");
	strcpy(sendbuf.pass,pass);
	sendbuf.oport=oport;

	sleep(2);	
	sendto(m_socket,(char *)&sendbuf,sizeof(sendbuf)+1, 0,(struct sockaddr*)&srvaddr,sizeof(srvaddr));
		
	len=sizeof(srvaddr);
	recvbuf.isnat=false;
	strcpy(recvbuf.oip,"0.0.0.0");
	strcpy(recvbuf.start,"vpn0");
	strcpy(recvbuf.pass,"");
	recvbuf.oport=0;
	setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
	recvfrom(m_socket, (char *)&recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&srvaddr, &len);
	if(strcmp(recvbuf.start,"vpn1")==0)
		{
			cout<<"start vpn1 thread1.....\n"<<endl;
			directvpn(lport,recvbuf.oip,recvbuf.oport);
			close(m_socket);
			return 1;	
		}
	else
		{
			if(strcmp(recvbuf.start,"vpn2")==0)
			{
			cout<<"start vpn2 thread2.....\n"<<endl;
			close(m_socket);
			relayvpn();
			return 1;
			
			}
			else
				{
				cout<<"start error.....\n"<<endl;
				close(m_socket);
				return 0;
				}
		}
return 0;
}


void *keepalive(void *arg)
{
	char recvBuf[10];
	int m_socket;
	socklen_t  len;
	struct sockaddr_in srvaddr;
	if ((m_socket = socket(AF_INET,SOCK_DGRAM,0)) < 0)		
	{
		printf("keepalive socket error!\n");	
		return NULL;
	}
	bzero(&srvaddr,sizeof(srvaddr));
	srvaddr.sin_family = AF_INET;
	srvaddr.sin_port = htons(7004);
	srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(m_socket, (struct sockaddr*)&srvaddr, sizeof(srvaddr))<0)
	{
		printf("keepalive bind cliaddr false!22\n");
		return NULL;
        }
	len = sizeof(srvaddr);
	while(1)
	{
		sleep(1);
		memset(recvBuf, 0, sizeof(recvBuf));
		recvfrom(m_socket, recvBuf, 10, 0, (struct sockaddr*)&srvaddr, &len);
		struct timeval timeout={2,0};
		setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
		if(strlen(recvBuf)>0)
			sendto(m_socket,"1",2, 0,(struct sockaddr*)&srvaddr,sizeof(srvaddr));
	}
}


int testalive(char ip[])
{
	int m_socket;
	socklen_t  len;
	char recvbuf[MAX_LEN];
	struct sockaddr_in Srvaddr;
	if ((m_socket = socket(AF_INET,SOCK_DGRAM,0)) < 0)		
	{
		printf("testalive socket error!\n");
		return 0;
	}
	bzero(&Srvaddr,sizeof(Srvaddr));
	Srvaddr.sin_family = AF_INET;
	Srvaddr.sin_port = htons(7004);
	Srvaddr.sin_addr.s_addr = inet_addr(ip);
	struct timeval timeout={2,0};
	setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
	sendto(m_socket, "1", 2, 0, (struct sockaddr*)&Srvaddr, sizeof(Srvaddr));
	
	setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
	len=sizeof(Srvaddr);
	memset(recvbuf,0,sizeof(recvbuf));
	recvfrom(m_socket, recvbuf, MAX_LEN, 0, (struct sockaddr*)&Srvaddr, &len);
	close(m_socket);
	if(recvbuf[0]=='1')
		return 1;
	else
		return 0;
}


static inline void WaitFdWriteable(int Fd,struct timeval tv)
{
    fd_set WriteSetFD;
    FD_ZERO(&WriteSetFD);
    FD_SET(Fd, &WriteSetFD);
    if (select(Fd + 1, NULL, &WriteSetFD, NULL, &tv) < 0) 
	  printf("select error\n");
}

void * recvthreadtcp(void *arg)
{
	Sendtoclient sendbuf,recvbuf;
    int skfd,cnfd;
	socklen_t  addr_len;
    struct sockaddr_in srv_addr,clt_addr;
	struct timeval tv;
   
    if(-1 == (skfd=socket(AF_INET,SOCK_STREAM,0)))
    {
        return NULL;
    }

    bzero(&srv_addr,sizeof(struct sockaddr_in));
    srv_addr.sin_family=AF_INET;
    srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    srv_addr.sin_port=htons(7004);

    if(-1 == bind(skfd,(struct sockaddr *)(&srv_addr),sizeof(struct sockaddr)))
    {
         perror("Bind error:");
         return NULL;
    }

    if(-1 == listen(skfd,4))
         return NULL;

    while(1)
    {
        addr_len=sizeof(struct sockaddr_in);
        if(-1 == (cnfd=accept(skfd,(struct sockaddr *)(&clt_addr),&addr_len)))
             return NULL;

		tv.tv_sec = 8;
        tv.tv_usec = 0;
		fd_set ReadSetFD;
		FD_ZERO(&ReadSetFD);
		FD_SET(cnfd, &ReadSetFD);
	
		if (select(cnfd + 1, &ReadSetFD, NULL, NULL, &tv) < 0) 
		{
			 printf("select error1111111111111\n");
		}

		if (FD_ISSET(cnfd, &ReadSetFD)) 
		{
			recvbuf.isnat=false;
			strcpy(recvbuf.oip,"0.0.0.0");
			strcpy(recvbuf.start,"vpn0");
			strcpy(recvbuf.pass,"");
			recvbuf.oport=0;
			
			if (read(cnfd, (char *)&recvbuf, sizeof(recvbuf)) > 0) 
			{

					recvbuf.oport=ntohl(recvbuf.oport);
					cout<<"isnat="<<recvbuf.isnat<<endl;
					cout<<"publicip="<<recvbuf.oip<<endl;
					cout<<"publicport="<<recvbuf.oport<<endl;
					cout<<"pass="<<recvbuf.pass<<endl;
					cout<<"start="<<recvbuf.start<<endl;

					int k=sizeof(recvbuf);
					cout<<"sizeof(recvbuf)="<<k<<endl;
					
					if(strcmp(recvbuf.start,"start")==0 )
					{
						testnat(&lport,&oport,oip,&isnat);
						sleep(2);
						sendbuf.isnat=isnat;
						strcpy(sendbuf.oip,oip);
						strcpy(sendbuf.pass,"");
						sendbuf.oport=oport;
						if(isnat==true&&recvbuf.isnat==true)
						{
							strcpy(sendbuf.start,"vpn1");
							cout<<"start vpn1 thread1.....\n"<<endl;
							WaitFdWriteable(cnfd,tv);
							write(cnfd,(char *)&sendbuf,sizeof(sendbuf));
							sleep(2);
							directvpn(lport,recvbuf.oip,recvbuf.oport);
						}
						else
						{
							strcpy(sendbuf.start,"vpn2");
							cout<<"start vpn2 thread2.....\n"<<endl;
							WaitFdWriteable(cnfd,tv);
							write(cnfd,(char *)&sendbuf,sizeof(sendbuf)); 
							sleep(2);
							relayvpn();
						}

				     }
					else
					{
						recvbuf.isnat=false;
						strcpy(recvbuf.oip,"0.0.0.0");
						strcpy(recvbuf.start,"vpn0");
						strcpy(recvbuf.pass,"");
						recvbuf.oport=0;
						WaitFdWriteable(cnfd,tv);
						write(cnfd,(char *)&sendbuf,sizeof(sendbuf)); 
					}
			
		    }
	     }
	 close(cnfd);    
     }
     close(skfd);
	 return 0;
}

int sendthreadtcp()
{
	timeflag++;
	Sendtoclient sendbuf,recvbuf;
	struct timeval tv;
    int sockfd;
    struct sockaddr_in dest;
	testnat(&lport,&oport,oip,&isnat);
	sleep(2);	

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        return 0;
    }

    tv.tv_sec = 6;
    tv.tv_usec = 0;
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(7004);
    if (inet_aton("127.0.0.1", (struct in_addr *) &dest.sin_addr.s_addr) == 0)
        return 0;
  
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) 
        return 0;
   	
	fd_set ReadSetFD,WriteSetFD;
	FD_ZERO(&ReadSetFD);
	FD_SET(sockfd, &ReadSetFD);
	FD_SET(sockfd, &WriteSetFD);
	
	if (select(sockfd + 1, NULL, &WriteSetFD,NULL, &tv) < 0) 
	{
		 return 0;
	}

	if (FD_ISSET(sockfd, &WriteSetFD)) 
	{
		if(timeflag>3)
			sendbuf.isnat=false;
		else
			sendbuf.isnat=isnat;
		strcpy(sendbuf.oip,oip);
		strcpy(sendbuf.start,"start");
		strcpy(sendbuf.pass,pass);
		sendbuf.oport=oport;
		write(sockfd, (char *)&sendbuf,sizeof(sendbuf)+1);
	}	

	if (select(sockfd + 1, &ReadSetFD, NULL, NULL, &tv) < 0) 
	{
		 return 0;
	}		
	recvbuf.isnat=false;
	strcpy(recvbuf.oip,"0.0.0.0");
	strcpy(recvbuf.start,"vpn0");
	strcpy(recvbuf.pass,"");
	recvbuf.oport=0;

	if (FD_ISSET(sockfd, &ReadSetFD)) 
	{
		read(sockfd, (char *)&recvbuf, sizeof(recvbuf)); 
			
		if(strcmp(recvbuf.start,"vpn1")==0)
		{
			cout<<"start vpn1 thread1.....\n"<<endl;
			directvpn(lport,recvbuf.oip,recvbuf.oport);
			close(sockfd);
			return 1;	
		}
		else
		{
			if(strcmp(recvbuf.start,"vpn2")==0)
			{
			cout<<"start vpn2 thread2.....\n"<<endl;
			close(sockfd);
			relayvpn();
			return 1;
			
			}
			else
				{
				cout<<"start error.....\n"<<endl;
				close(sockfd);
				return 0;
				}
		 }
			
      }	
		return 0;
}

uint16_t in_cksum(uint16_t *addr, int len)  
{
	  int nleft = len;
	  uint32_t sum = 0;
	  uint16_t *w = addr;
	  uint16_t answer = 0;
	  while (nleft > 1) {
		  sum += *w++;
		  nleft -= 2;
	  }  
  
	  if (nleft == 1) {
		  *(unsigned char *)(&answer) = *(unsigned char *)w ;
		  sum += answer;
	  }
  
	  sum = (sum >> 16) + (sum & 0xffff);
	  sum += (sum >> 16);
	  answer = ~sum;
	  return(answer);  
  }


void send_echo_req(int sockfd, struct sockaddr_in *dstaddr)  
{
    char buf[100];
    size_t len = sizeof(struct icmp);
    struct icmp *icmp;
    socklen_t dstlen = sizeof(struct sockaddr_in);

    bzero(buf, sizeof(buf));
    icmp = (struct icmp *)buf;
    icmp->icmp_type = ICMP_ECHO;//8
    icmp->icmp_code = 0;
    icmp->icmp_id = getpid();
    icmp->icmp_seq = 1;
    icmp->icmp_cksum = in_cksum((uint16_t *) icmp, sizeof(struct icmp));
    if (sendto(sockfd, buf, len, 0, (struct sockaddr *)dstaddr, dstlen) == -1)
       cout<<"sendto error"<<endl;  
}

int  recv_echo_reply(int sockfd)  
{
    char buf[100];
    ssize_t n;
    struct ip *ip;
    struct icmp *icmp;

		struct timeval tv;
		tv.tv_sec = 4;
        tv.tv_usec = 0;
		fd_set ReadSetFD;
		FD_ZERO(&ReadSetFD);
		FD_SET(sockfd, &ReadSetFD);
    
	if (select(sockfd + 1, &ReadSetFD, NULL, NULL, &tv) < 0) 
			{
				 printf("select error1111111111111\n");
				 return 0;
			}

	if (FD_ISSET(sockfd, &ReadSetFD)) 
	{
     
        if ((n = read(sockfd, buf, sizeof(buf))) == -1)
        {
        	cout<<"read"<<endl;
			return 0;
        }
        ip = (struct ip *)buf;

        if (ip->ip_p != IPPROTO_ICMP) 
		{
            fprintf(stderr, "protocol error.");
            return 0;
        }

        icmp = (struct icmp *)(buf + sizeof(struct ip));

        if (icmp->icmp_type == ICMP_ECHOREPLY) 
		{
            if (icmp->icmp_id != getpid()) 
               return 0;
			else 
               return 1;      
         } 
	  }
	return 0;
}


int icmptest(char ip[])  
{
		int sockfd;
	    struct sockaddr_in dstaddr;  
	    if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
	    	{
	    		cout<<"socket error"<<endl;
				close(sockfd);
				return 0;
	    	}

	    bzero(&dstaddr, sizeof(dstaddr));
	    dstaddr.sin_family = AF_INET;
	    dstaddr.sin_port = htons(22222);

	    if (inet_pton(AF_INET, ip, &dstaddr.sin_addr) <= 0)
	        cout<<"inet_pton"<<endl;

	    send_echo_req(sockfd, &dstaddr);	
	    if(recv_echo_reply(sockfd)==1)
		{
			close(sockfd);
			return 1;
	    }
		else
		{
			close(sockfd);
			return 0;
		}
}

void setconnect(int connect)
{
	char tmp[10];
	if(connect==1)
	{
		readuci("uci get routedif.@routedif[0].interconnect",tmp);
		if(tmp[0]!='1')
		{
		    system("uci set routedif.@routedif[0].interconnect=1");
			system("uci commit routedif");
		}
	}
	else
	{
		readuci("uci get routedif.@routedif[0].interconnect",tmp);
		if(tmp[0]!='0')
		{
		    system("uci set routedif.@routedif[0].interconnect=0");
			system("uci commit routedif");
		}
	}
}


void * recvremote(void *arg)
{
	SendRemote sendbuf,recvbuf;
    int skfd,cnfd;
	socklen_t  addr_len;
    struct sockaddr_in srv_addr,clt_addr;
	struct timeval tv;
   
    if(-1 == (skfd=socket(AF_INET,SOCK_STREAM,0)))
    {
        return NULL;
    }

    bzero(&srv_addr,sizeof(struct sockaddr_in));
    srv_addr.sin_family=AF_INET;
    srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    srv_addr.sin_port=htons(7008);

    if(-1 == bind(skfd,(struct sockaddr *)(&srv_addr),sizeof(struct sockaddr)))
    {
         perror("Bind error:");
         return NULL;
    }

    if(-1 == listen(skfd,4))
         return NULL;

    while(1)
    {
        addr_len=sizeof(struct sockaddr_in);
        if(-1 == (cnfd=accept(skfd,(struct sockaddr *)(&clt_addr),&addr_len)))
             return NULL;

		tv.tv_sec = 4;
        tv.tv_usec = 0;
		fd_set ReadSetFD;
		FD_ZERO(&ReadSetFD);
		FD_SET(cnfd, &ReadSetFD);
	
		if (select(cnfd + 1, &ReadSetFD, NULL, NULL, &tv) < 0) 
		{
			 printf("select error1111111111111\n");
		}

		if (FD_ISSET(cnfd, &ReadSetFD)) 
		{

			cout<<"recv rboot"<<endl;
			strcpy(recvbuf.reboot,"");
			strcpy(recvbuf.pass,"");
			if (read(cnfd, (char *)&recvbuf, sizeof(recvbuf)) > 0) 
			{
			//cout<<"recv rboot"<<endl;
		//	cout<<recvbuf.reboot<<endl;
		//	cout<<recvbuf.pass<<endl;
					if(strcmp(recvbuf.reboot,"reboot")==0 )
					{
						strcpy(sendbuf.reboot,"rebootok");
						strcpy(sendbuf.pass,"");
						WaitFdWriteable(cnfd,tv);
						write(cnfd,(char *)&sendbuf,sizeof(sendbuf));
						sleep(3);
						system("reboot -f");
				     }
					else
					{
						strcpy(sendbuf.reboot,"rebooterror");
						strcpy(sendbuf.pass,"");
						WaitFdWriteable(cnfd,tv);
						write(cnfd,(char *)&sendbuf,sizeof(sendbuf));

					}
			
		    }
	     }
	 close(cnfd);    
     }
     close(skfd);
	 return 0;
}



int main(int argc, char* argv[])
{

   readuci("uci get routedif.@routedif[0].vpnproto",vpnproto);
   sleep(2);
	if(strcmp(vpnproto,"vpnserver")==0 || strcmp(vpnproto,"vpnclient")==0)
	{
		system("/www/kenn-admin/cgi-bin/directconnect &");
		sleep(3);
		exit(1);
	}
	
	if(strcmp(vpnproto,"t2uvpn")==0 )
	{
		system("/jffs/sbin/t2uvpn &");
		sleep(3);
		exit(1);
	}

	

   sleep(2);
   system("killall openvpn");
   system("killall relayvpn");
   system("killall edge");
   system("killall directconnect");
   readuci("uci get network.lan.ipaddr",lanip);
   //ledinit();
   readuci("uci get network.lan.ipaddr",lanip);
   readuci("uci get routedif.serverip",serverip);
   readuci("uci get routedif.@routedif[0].remoteid",uuid);
   readuci("uci get routedif.@routedif[0].remotepass",pass);
   	
 
   if(strcmp(lanip,"192.168.19.251")==0)
	   {
	   t2u_init("nat.vveye.net",8000,NULL);	
	     sleep(8);
		   sprintf(remotelanip,"%s","192.168.19.252");
		   sprintf(staticvpnip,"%s","192.19.19.251");
		   sprintf(remotevpnip,"%s","192.19.19.252");
		   routea=1;
		   t2u_add_port_v3(uuid,pass,"127.0.0.1",7004,7004);
	   }
   else
	   {
	     	sleep(8);
		   sprintf(remotelanip,"%s","192.168.19.251");
		   sprintf(staticvpnip,"%s","192.19.19.252");
		   sprintf(remotevpnip,"%s","192.19.19.251");
		   routea=0;
		   t2u_svr_init("nat.vveye.net",8000,NULL,uuid,200);
		   t2u_svr_set_passwd(pass);
	   }

   if(routea==1)
   	{
	   pthread_t keepaliveid;
	   int ret;
	   pthread_attr_t tattr;
	   ret = pthread_attr_init (&tattr);   
	   	ret = pthread_create(&keepaliveid,NULL,keepalive,NULL); 
	   if(ret != 0)
	   {
		   printf("creat staticvpn pthread error1!\n");
	   }
   
   		n2n();
	    sleep(3);
   		while(1)
   		{
			/*if(icmptest(serverip)==1)
				led(INTERNET,1);
			else
				led(INTERNET,0);
			*/
   			int ret=0;
			if(testalive(remotevpnip)==0)
			{
			    cout<<"n2n send error"<<endl;
				if(t2u_port_status(7004,NULL)==1)
				{
					cout<<"t2u send test"<<endl;
					ret=sendthreadtcp();	
				}
			}
			else
			{
				cout<<"n2n send test"<<endl;
				ret=sendthread(remotevpnip);
			}
			
	  		if(ret==0)
	  		{
				sleep(30);
				printf("send error,no client ,sleep 30second\n");		
	  		}
			else
			{
				int time=0;
				while(time<5)
				{
					time++;
					if(testalive(remotelanip))
					{
						cout<<"connect ok .............."<<endl;
						//led(CONNECT,1);
						setconnect(1);
						timeflag=0;
						time=0;
					}
					else
					{
						cout<<"cant connect remote 55555555"<<endl;
						setconnect(0);
						//led(CONNECT,0);
					}
			
					sleep(15);
				}	
			}
   		}
   	}
   else
   	{
   	   pthread_t recvthreadid, keepaliveid,recvthreadtcpid,rebootid;
	   int ret;
	   pthread_attr_t tattr;
	   ret = pthread_attr_init (&tattr);   
	   ret = pthread_create(&recvthreadid,NULL,recvthread,NULL); 
	   if(ret != 0)
	   {
		   printf("creat staticvpn pthread error1!\n");
	   }
	   	ret = pthread_create(&keepaliveid,NULL,keepalive,NULL); 
	   if(ret != 0)

	   
	   {
		   printf("creat staticvpn pthread error1!\n");
	   }
	   ret = pthread_create(&recvthreadtcpid,NULL,recvthreadtcp,NULL); 
	   if(ret != 0)
	   {
		   printf("creat staticvpn pthread error1!\n");
	   }


	   	   ret = pthread_create(&rebootid,NULL,recvremote,NULL); 
	   if(ret != 0)
	   {
		   printf("creat staticvpn pthread error1!\n");
	   }
	   
		n2n();
	    while(1)
	   	{	
	   	/*	if(icmptest(serverip)==1)
				led(INTERNET,1);
			else
			{
				if(icmptest(serverip)==1)
					led(INTERNET,1);
				else
					led(INTERNET,0);
			}*/
			
			if(icmptest(remotelanip)==1)
			{ 
						cout<<"connect ok .............."<<endl;
						setconnect(1);
						//led(CONNECT,1);
			}
			else
			{
					cout<<"cant connect remote 55555555"<<endl;
					setconnect(0);
						//led(CONNECT,0);
			}
			sleep(15);
	   	}
   	   
   	}  
   return 0;
}

















